package net.pulseproject.router.systemtest;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;

import net.pulseproject.router.config.parser.LineConfig;
import net.pulseproject.router.modules.Module;
import net.pulseproject.router.modules.useable.MidiReceiverModule;
import net.pulseproject.router.modules.useable.MidiTransmitterModule;

public abstract class LineConfigBuilder {
	
	private String id;
	private String type;
	private final Collection<String> outgoingIds = new LinkedHashSet<String>();
	private final Map<String, Object> properties = new LinkedHashMap<String, Object>();
	
	
	public LineConfigBuilder(final Class<? extends Module> moduleClass) {
		this.type = moduleClass.getSimpleName();
	}
	
	protected final void setId(final String pId) {
		this.id = pId;
	}
	
	protected final String getId() {
		return this.id;
	}
	
	protected final String getType() {
		return this.type;
	}
	
	protected final void addProperty(final String key, final Object value) {
		this.properties.put(key, value);
	}
	
	protected final Map<String, Object> getProperties() {
		return this.properties;
	}
	
	protected final Collection<String> getOutgoingIds() {
		return this.outgoingIds;
	}
	
	public abstract LineConfig build();

	
	
	
	public static class MidiTransmitterConfigBuilder extends LineConfigBuilder {
		
		public MidiTransmitterConfigBuilder() {
			super(MidiTransmitterModule.class);
		}

		public final MidiTransmitterConfigBuilder id(final String pId) {
			this.setId(pId);
			return this;
		}

		public final MidiTransmitterConfigBuilder addOut(final String out) {
			this.getOutgoingIds().add(out);
			return this;
		}
		
		public final MidiTransmitterConfigBuilder port(final String port) {
			this.addProperty("port", port);
			return this;
		}
		
		public final MidiTransmitterConfigBuilder channel(final int channel) {
			this.addProperty("channel", Integer.valueOf(channel));
			return this;
		}

		public final MidiTransmitterConfigBuilder controller(final int controller) {
			this.addProperty("controller", Integer.valueOf(controller));
			return this;
		}
		
		@Override
		public final LineConfig build() {
			return new LineConfig(this.getId(), this.getType(), this.getOutgoingIds(), this.getProperties());
		}
	}
	
	
	
	public static class MidiReceiverConfigBuilder extends LineConfigBuilder {
		
		public MidiReceiverConfigBuilder() {
			super(MidiReceiverModule.class);
		}

		public final MidiReceiverConfigBuilder id(final String pId) {
			this.setId(pId);
			return this;
		}

		public final MidiReceiverConfigBuilder port(final String port) {
			this.addProperty("port", port);
			return this;
		}
		
		public final MidiReceiverConfigBuilder channel(final int channel) {
			this.addProperty("channel", Integer.valueOf(channel));
			return this;
		}

		public final MidiReceiverConfigBuilder controller(final int controller) {
			this.addProperty("controller", Integer.valueOf(controller));
			return this;
		}
		
		@Override
		public final LineConfig build() {
			return new LineConfig(this.getId(), this.getType(), this.getOutgoingIds(), this.getProperties());
		}
	}
	
}
